import { EcsComponent } from "./EcsComponent";
import { EcsEntity } from "./EcsEntity";
import { EcsWorld } from "./EcsWorld";

/**组件快照 */
export class EcsComponentSnapshot {
    public compId: number;
    public data: any;

    static fromComponent(comp: EcsComponent) {
        let snapshot = new EcsComponentSnapshot();
        snapshot.compId = EcsComponent.getId(comp);
        snapshot.data = JSON.parse(JSON.stringify(comp));
        return snapshot;
    }
}

/**实体快照 */
export class EcsEntitySnapshot {
    public id: number;
    public typeName: string | number;
    public components: EcsComponentSnapshot[] = [];

    static fromEntity(entity: EcsEntity) {
        let snapshot = new EcsEntitySnapshot();
        snapshot.id = entity.id;
        snapshot.typeName = entity._factory.name
        for (let index = 0; index < entity.__comps.length; index++) {
            const comp = entity.__comps[index];
            if (comp) {
                snapshot.components.push(EcsComponentSnapshot.fromComponent(comp));
            }

        }
        return snapshot;
    }
}

/**世界快照 */
export class EcsWorldSnapshot {
    public frame: number;
    public nextEntityGenId: number;
    public singletons: any[] = [];
    public entities: EcsEntitySnapshot[] = [];


    static fromWorld(word: EcsWorld) {
        let snapshot = new EcsWorldSnapshot();
        snapshot.frame = word.frameCount;
        snapshot.nextEntityGenId = word.nextEntityGenId;


        for (let index = 0; index < word.singletons.length; index++) {
            const singleton = word.singletons[index];
            if (singleton) {
                snapshot.singletons.push(JSON.parse(JSON.stringify(singleton)));
            }
        }


        for (const key in word.entities) {
            if (Object.prototype.hasOwnProperty.call(word.entities, key)) {
                const entity = word.entities[key];
                snapshot.entities.push(EcsEntitySnapshot.fromEntity(entity));
            }
        }

        return snapshot;
    }

    /**还原世界 */
    static restoreWorld(world: EcsWorld, snapshot: EcsWorldSnapshot) {
        world.frameCount = snapshot.frame;

        for (let index = 0; index < snapshot.singletons.length; index++) {
            Object.assign(world.singletons[index], snapshot.singletons[index])
        }

        for (const key in snapshot.entities) {
            if (Object.prototype.hasOwnProperty.call(snapshot.entities, key)) {
                const entitySnapshot = snapshot.entities[key];
                let entity = world.entities[entitySnapshot.id];

                entity = world.addEntity(entitySnapshot.typeName, entitySnapshot.id);
                for (let index = 0; index < entitySnapshot.components.length; index++) {
                    const compSnapshot = entitySnapshot.components[index];
                    let comp = entity.__comps[compSnapshot.compId];

                    Object.assign(comp, compSnapshot.data);
                    // entity.__comps[compSnapshot.compId] = comp;
                    // entity.__componentsID += Math.pow(2, compSnapshot.compId);
                }
            }
        }

        world.nextEntityGenId = snapshot.nextEntityGenId;
    }
}